import javax.swing.*;
import java.io.*;
import java.io.IOException;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.*;

public class JavaStream {
    public static <T> void showstream(String t,Stream<T> stream)
    {
        int size=30;
        List<T>firstElements=stream.limit(size+1).collect(Collectors.toList());
        System.out.print(t+":");
        for(int i=0;i<firstElements.size();++i)
        {
            if(i>0) System.out.print(", ");
            if(i<size) System.out.print(firstElements.get(i));
            else System.out.print("...");
        }
        System.out.println();
    }
    //流分割
    public static Stream<String> codePoint(String s)
    {
        ArrayList<String> result=new ArrayList<String>();
        int i=0;
        while(i<s.length())
        {
            int j=s.offsetByCodePoints(i,1);
            result.add(s.substring(i,j));
            String a=s.substring(i,j);
            i=j;
        }
        return result.stream();
    }
    public static void main(String[] args) throws IOException
    {
        Integer[] sz=new Integer[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        String co=new String(Files.readAllBytes(Paths.get("E:\\java-learn\\src\\words.txt")), StandardCharsets.UTF_8);
        Integer quan=1;
        long c=0;//筛选后，流的数量
        if(quan==0)
        {
            List<String> words=List.of(co.split("\\PL+"));
            for(String w:words) { if(w.length()>1) c++; }
            System.out.println(c);
            c=words.stream().filter(w->w.length()>1).count();
            System.out.println(c);
            c=words.parallelStream().filter(w->w.length()>1).count();//并行流
            System.out.println(c);
        }
        else if(quan==1)
        {
            /*
            * 有限流
            */
            // 使用Stream.of()函数读取文件中的多个流
            Stream<String> words= Stream.of(co.split("\\PL+"));
            //filter函数用来对流中数据进行筛选
            showstream("words",words);
            //使用哪个Stream.of()函数读取自定义的多个流
            Stream<String> song=Stream.of("g","d","t","s");
            showstream("song",song);
            //创建空流
            Stream<String> silence=Stream.empty();
            Stream.ofNullable(silence);//ofNullable函数如果silence为空流返回一个空流，否则返回包含silence的流
            showstream("silence",silence);
            /*
            *
            * 无限流
            *
            */
            //使用generate()函数创建无限流，如果不希望流无限的创建下去，可以在generate()函数后使用limit()函数进行限制
            Stream<String> echo=Stream.generate(()->"Echo").limit(10);//limit用于限制无限流中的流数量，forEach用于输出流中数据
            showstream("echo",echo);
            Stream<Double> randoms=Stream.generate(Math::random).limit(10);
            showstream("randoms",randoms);
            //使用iterate()函数创建无限流，以0,f(0)=1,f(f(0))=2,f(f(f(0)))=3,迭代创建0123...,第一个元素为种子seed，下面部分0为种子
            BigInteger limit=new BigInteger("20");
            Stream<BigInteger> integers=Stream.iterate(BigInteger.ZERO,n->n.add(BigInteger.ONE)).limit(10);
            showstream("integers",integers);
            //除了使用limit函数限制无限流,还可以在iterate()函数中增加限制条件
            //a.compareTo(b)函数用于比较大小,a>b时,返回1,a=b时,返回0,a<b时,返回-1
            Stream<BigInteger> integers1=Stream.iterate(BigInteger.ZERO,n-> n.compareTo(limit) < 0, n->n.add(BigInteger.ONE));
            showstream("integers1",integers1);
            List<String> word=List.of(co.split("\\PL+"));
            List<List<String>> stream=word.stream().map(w->codePoint(w).collect(Collectors.toList())).collect(Collectors.toList());
            for (List<String> a:stream) { System.out.println(a); }
            Stream<String> your=codePoint("your");
            your.forEach(a->System.out.println(a));
            Stream<Stream<String>> yourboat=word.stream().map(w->codePoint(w));
            /*
            * 收集结果
            * */
            Stream<String> word1=word.stream().flatMap(w->codePoint(w));
            List<String> result=word1.collect(Collectors.toList());//collect函数可以将stream流转化为List等其他的Collection集合类型
            Stream<String> word2=word.stream().flatMap(w->codePoint(w));
            TreeSet<String> result1=word2.collect(Collectors.toCollection(TreeSet::new));
            Stream<String> word3=word.stream().flatMap(w->codePoint(w));
            String result_join=word3.collect(Collectors.joining());//joining函数有分隔符参数时可以增加分隔符，为空时可以连接流中元素
            System.out.println(result+" "+result1+" "+result_join);
            Stream<String> word4=word.stream().flatMap(w->codePoint(w));
            Stream<String> randoms1=Stream.of(co.split("\\PL+"));
            //简约流的结果，简约为总和、平均数、最大值、最小值等可以用IntSummaryStatistics
            IntSummaryStatistics summary=randoms1.collect(Collectors.summarizingInt(String::length));
            Double ave=summary.getAverage();
            Integer max=summary.getMax();
            System.out.println(ave+" "+max);

        }
        else if(quan==2)
        {
            List<String> words=List.of(co.split("\\PL+"));
            /*
            * 抽取子流和组合流
            */
            Stream<String> words1=Stream.of(co.split("\\PL+")).skip(1);
            showstream("words1",words1);
            Stream<String> numbers=codePoint("a123456rty789uio")
                    .takeWhile(s->"0123456789".contains(s));//takeWhile()函数的碰到第一个使其为假的元素时，停止，只能收集第一个使其为假的元素之前的所有元素，之后的元素不收集
            showstream("numbers",numbers);
            Stream<String> without=codePoint("12hello123 world")
                    .dropWhile(s->"0123456789".contains(s));//dropWhile()函数，在碰到第一个使其为假的元素时，将该元素以及后面的所有符合和不符合条件的元素都收集起来
            showstream("without",without);
            Stream<String> combined=Stream.concat(codePoint("hello"),codePoint("world"));//concat()函数将两个流连接起来
            showstream("combined",combined);
            /*
            * 其他流的转换
            * */
            Stream<String> uniqueWords=Stream.of(co.split("\\PL+")).distinct();
            showstream("uniqueWords",uniqueWords);
            Stream<String> longestFirst=words.stream().sorted(Comparator.comparing(String::length).reversed());
            showstream("longestFirst",longestFirst);
            Object[] powers=Stream.iterate(1.0,p->p*2).peek(e->System.out.print("Fetching"+e)).limit(20).toArray();
            Stream<String> longestFirst1=words.stream().sorted(Comparator.comparing(String::length).reversed());
            String[] sortwords=longestFirst1.toArray(String[]::new);
        }
        else if(quan==3)
        {
            /*
            * 简单简约    将流简约为可以在程序中使用的非流值，包括count，max，min等
            * */
            Stream<String> words=Stream.of(co.split("\\PL+"));
            Optional<String> largest=words.max(String::compareToIgnoreCase);
            System.out.println("largest:"+largest.orElse(""));
            Stream<String> words1=Stream.of(co.split("\\PL+"));
            Optional<String> startsWithQ=words1.filter(s->s.startsWith("q")).findFirst();
            System.out.println("startsWithQ:"+startsWithQ.orElse(""));
            Stream<String> words2=Stream.of(co.split("\\PL+"));
            Optional<String> startsWithQ1=words2.parallel().filter(s->s.startsWith("p")).findAny();
            System.out.println("startsWithQ1:"+startsWithQ1.orElse(""));
            Stream<String> words3=Stream.of(co.split("\\PL+"));
            boolean aWordStartWithq=words3.parallel().anyMatch(s->s.startsWith("q"));//还有allMatch和noneMatch
            System.out.println(aWordStartWithq);
            /**
             *Optional类型
             */
            String result=startsWithQ1.orElse("");//当result值为空时，返回空字符串“”
            System.out.println(result);
            String result1=startsWithQ1.orElseGet(()->System.getProperty("myapp.default"));//当result值为空时，返回NULL
            System.out.println(result1);
            String result2=startsWithQ1.orElseThrow(IllegalStateException::new);//当result值为空时，报错
            System.out.println(result2);

        }
        else if(quan==4)
        {
            Stream<String> words=Stream.of(co.split("\\PL+"));
            List<String> result=words.collect(Collectors.toList());


        }
    }
}
